﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;
using Web.Framework.Svc;
using System.Text;

namespace Web.Framework
{
    public abstract class BaseWebPage : System.Web.UI.Page
    {
        protected BaseWebMasterPage masterPage { get; set; }

        public static bool IsAdmin
        {
            get
            {
                return Convert.ToBoolean(HttpContext.Current.Session["IsAdmin"]);
            }
            set
            {
                HttpContext.Current.Session["IsAdmin"] = value;
            }
        }

        public static string DisplayUserName
        {
            get
            {
                return Convert.ToString(HttpContext.Current.Session["DisplayUserName"]);
            }
            set
            {
                HttpContext.Current.Session["DisplayUserName"] = value;
            }
        }

        public static int ApplicationId
        {
            get
            {
                if (HttpContext.Current.Request.Cookies["appId"] == null)
                {
                    throw new Exception("La aplicación no está registrada");
                }

                return Convert.ToInt32(HttpContext.Current.Request.Cookies["appId"].Value);
            }
            set
            {
                HttpCookie cookie = HttpContext.Current.Response.Cookies["appId"];
                if (cookie == null)
                {
                    cookie = new HttpCookie("appId");
                    HttpContext.Current.Response.Cookies.Add(cookie);
                }

                cookie.Value = value.ToString();
            }
        }
        
        public static bool IsCompanyRegistered()
        {
            return HttpContext.Current.Request.Cookies["companyId"] != null;
        }

        public static int CompanyId
        {
            get
            {                
                if (HttpContext.Current.Request.Cookies["companyId"] == null)
                {
                    throw new Exception("La empresa no está registrada");
                }

                return Convert.ToInt32(HttpContext.Current.Request.Cookies["companyId"].Value);
            }
            set
            {
                HttpCookie cookie = HttpContext.Current.Response.Cookies["companyId"];
                if (cookie == null)
                {
                    cookie = new HttpCookie("companyId");
                    HttpContext.Current.Response.Cookies.Add(cookie);

                }

                cookie.Value = value.ToString();
            }
        }

        public static string UserName
        {
            get
            {
                return HttpContext.Current.User.Identity.Name;
            }
        }

        protected override void OnInit(EventArgs e)
        {
            if (!DesignMode)
            {
                base.OnInit(e);

                if (Context.Session != null)
                {
                    //Tested and the IsNewSession is more advanced then simply checking if 
                    // a cookie is present, it does take into account a session timeout, because 
                    // I tested a timeout and it did show as a new session
                    if (Session.IsNewSession)
                    {
                        // If it says it is a new session, but an existing cookie exists, then it must 
                        // have timed out (can't use the cookie collection because even on first 
                        // request it already contains the cookie (request and response
                        // seem to share the collection)
                        string szCookieHeader = Request.Headers["Cookie"];
                        if ((null != szCookieHeader) && (szCookieHeader.IndexOf("ASP.NET_SessionId") >= 0))
                        {
                            //Session.Abandon();
                            FormsAuthentication.SignOut();
                            Response.Redirect("/Account/Login.aspx");
                        }
                    }
                }
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            // Aplica seguridad a los botones
            ApplySecurity();
            base.OnPreRender(e);
        }

        protected override void OnPreLoad(EventArgs e)
        {
            if (!DesignMode)
            {
                masterPage = (BaseWebMasterPage)this.Master;
                if (masterPage != null)
                {
                    masterPage.baseWebPage = this;
                    masterPage.PreLoad();
                }
            }
        }

        /// <summary>
        /// Aplica la seguridad en los botones a la pantalla
        /// </summary>
        protected virtual void ApplySecurity()
        {
        }

        protected void LoadOperations(List<string> operations)
        {
            innerOperationsForUser.Clear();
            innerOperationsForUser.AddRange(operations);
        }

        protected List<string> innerOperationsForUser = new List<string>();
        protected List<string> OperationsForUser
        {
            get
            {
                return innerOperationsForUser;
            }
        }

        /// <summary>
        /// Testea si el usuario tiene permisos para la operación
        /// </summary>
        /// <param name="operation"></param>
        /// <returns></returns>
        public bool HasPermissionFor(string operation)
        {
            return IsAdmin || OperationsForUser.Where(o => o == operation).Count() > 0;
        }

        //protected void HasPermissionToSeeMe(string operation)
        //{
        //    if (!IsAdmin && !HasPermissionFor(operation))
        //    {
        //        this.RedirectDefault("No tiene permisos para realizar " + operation);
        //    }
        //}

        /// <summary>
        /// es un O entre las operaciones
        /// </summary>
        /// <param name="operation"></param>
        protected void HasPermissionToSeeMe(params string[] operation)
        {
            if (!IsAdmin)
            {
                bool hasPermission = false;
                foreach (string op in operation)
                {
                    hasPermission = HasPermissionFor(op);
                    if (hasPermission)
                        break;
                }

                if (!hasPermission)
                {
                    StringBuilder operationStrings = new StringBuilder();
                    string separador = string.Empty;

                    foreach (string s in operation)
                    {
                        operationStrings.Append(separador);
                        operationStrings.Append(s);
                        separador = ", ";
                    }

                    this.RedirectDefault("No tiene permisos para realizar " + operationStrings.ToString());
                }
            }
        }       

        public void RedirectDefault(string message)
        {
            // TODO: chequear la session
            Response.Redirect(string.Format("/App/Default.aspx?message={0}", message), true);
        }

        protected void BindAuditory(IAuditable auditableEntity)
        {
            Control ctrlBox = FindControlRecursive(this, "txtAuditFechaCreacion");
            TextBox txtBox;
            if (ctrlBox != null)
            {
                txtBox = (TextBox)ctrlBox;
                txtBox.Text = auditableEntity.AuditFechaCreacion.ToString("dd/MM/yyyy HH:mm");
            }

            ctrlBox = this.FindControlRecursive(this, "txtAuditUserNameCreacion");
            if (ctrlBox != null)
            {
                txtBox = (TextBox)ctrlBox;
                txtBox.Text = auditableEntity.AuditUserNameCreacion;
            }

            ctrlBox = this.FindControlRecursive(this, "txtAuditUserNameModificacion");
            if (ctrlBox != null)
            {
                txtBox = (TextBox)ctrlBox;
                txtBox.Text = auditableEntity.AuditUserNameModificacion;
            }

            ctrlBox = this.FindControlRecursive(this, "txtAuditFechaModificacion");
            if (ctrlBox != null && auditableEntity.AuditFechaModificacion.HasValue)
            {
                txtBox = (TextBox)ctrlBox;
                txtBox.Text = auditableEntity.AuditFechaModificacion.Value.ToString("dd/MM/yyyy HH:mm");
            }
        }

        protected Control FindControlRecursive(Control rootControl, string controlID)
        {
            if (rootControl.ID == controlID) return rootControl;

            foreach (Control controlToSearch in rootControl.Controls)
            {
                Control controlToReturn =
                    FindControlRecursive(controlToSearch, controlID);
                if (controlToReturn != null) return controlToReturn;
            }
            return null;
        }
    }
}